<?php
/**
 * Кэширования в системе.
 * @author nrnwest@gmail.com
 *
 */
class Arm_Cache
{
    
    /**
     * Флаг системы который указывает включать кеширования или
     * нет, каждый метод для создания объекта кэша должен его проверять.
     * @var bool
     */
    private $_cacheSystem = false;
    
    /**
     * Конфиг кеширования в системе application/cache.ini
     * @var Zend_Config
     */
    private $_config = null;
    
    /**
     * Названия backend по умолчанию.
     * @var string
     */
    private $_backendName = null;
    
    /**
     * Опции backend
     * @var array()
     */
    private $_backendOptions = array();
    
    /**
     * Zend_Log
     * 
     * @var Zend_Log
     */
    private $_logger;
    
    /**
     * Arm_Cache
     *
     * @var Arm_Cache
     */
    private static $_instance = null;
    
    private function __construct()
    {
        date_default_timezone_set(Arm_Core::getConfigApplication()->system->timezone);
        if(Arm_Core::getConfigApplication()->system->cache->on === '1') {
            $this->_cacheSystem = true;
        }
        $this->_config      = new Zend_Config_Ini(Arm_Core::getPathApplication() . 'configs/cache.ini');
        $this->_setLogger();
        $this->_backendName = ucfirst(strtolower($this->_config->default->backend));
        $sectionBackend     = 'backend' . $this->_backendName;
        $this->_backendOptions = $this->_config->{$sectionBackend}->toArray();
    }
    
        
    
    /**
     * Arm_Cache
     *
     * @return Arm_Cache
     */
    public static function getInstance()
    {
        if(self::$_instance === null) {
            self::$_instance = new Arm_Cache();
        }
        return self::$_instance;
    }
    
    /**
     * Установка логировщика.
     * 
     */
    private function _setLogger()
    {
        if($this->_config->frontendCore->logging === '1') {
           $logger = new Zend_Log(new Zend_Log_Writer_Stream(Arm_Core::getPathTemp() . 'log/cache_log'));
           $this->_logger = $logger;
        }
    }
    
    /**
     * Вернет главную директорию для хранения данных кешов
     * 
     * @return path
     */
    public function getPathRootFolderCache()
    {
        $path = Arm_Core::getPathTemp() . 'cache' . DIRECTORY_SEPARATOR; 
        if(is_dir($path) === false) {
            mkdir($path);
        }
        return $path;
    }
    
    /**
     * Zend_Cache_Frontend_Core
     * 
     * @return Zend_Cache_Core
     */
    public function getFrontendCore()
    {
        $frontendOptions = $this->_getFrontendConfig('frontendCore');
        $cache = Zend_Cache::factory('Core', $this->_backendName, $frontendOptions, $this->_backendOptions);
        return $cache;   
    }
    
    /**
     * Если $avtoSrart true будет автоматически вызван метод start, проверка наличия кэша
     * и его отдача.
     * 
     * @todo во время запуска дебуг панели устнавливаються сокиес, и кеширования
     * не возможно включить, потому нужно подумать как сделать....
     * Проблема - во время разботки с панелью отладки не возможно включить кеширования page
     * по умолчанию.
     * 
     * @param bool $avtoStart
     * @return Zend_Cache_Frontend_Page
     */
    public function getFrontendPage($avtoStart=true)
    {    
        $frontendOptions = $this->_getFrontendConfig('frontendPage');
        $frontendOptions['regexps'] = $this->_helperPageConfig($frontendOptions['regexps']);
        // Получаем настройки модуля
        $module = Arm_Core::getNameModuleRequestUri();
        if( false === $module ) {
            $module = 'default';
        }
        $config = Arm_Module::getInstance()->getConfigCache($module);
        if($config  !== false and $config->regexps  !== null) {
            $array = $config->regexps->toArray();
            $array = $this->_helperPageConfig($array);
            $frontendOptions['regexps'] = array_merge($frontendOptions['regexps'], $array);
        }
        /*@var $cache Zend_Cache_Frontend_Page */
        $cache = Zend_Cache::factory('Page', $this->_backendName, $frontendOptions, $this->_backendOptions);
        if($avtoStart) {
            $cache->start();
        }
        return $cache;
    }
    
    
    /**
     * Кеширования на основе местер файлов(файла), файлы за которыми следит система,
     * если они изменнны значит кеш сбрасываеться.
     * 
     * @param string|array $masterFiles путь к файлу(лам) за которыми нужно следить.
     * @return Zend_Cache_Frontend_File
     */
    public function getFrontendFile($masterFiles)
    {
        $masterFiles = (array) $masterFiles;
        $frontendOptions = $this->_getFrontendConfig('frontendFile');
        $frontendOptions['master_files'] = $masterFiles;
        $cache = Zend_Cache::factory('File', $this->_backendName, $frontendOptions, $this->_backendOptions);
        return $cache;   
    }
    
    /**
     * Zend_Cache_Frontend_Output
     * 
     * @return Zend_Cache_Frontend_Output
     */
    public function getFrontendOutput()
    {
        $frontendOptions = $this->_getFrontendConfig('frontendOutput');
        $cache = Zend_Cache::factory('Output', $this->_backendName, $frontendOptions, $this->_backendOptions);
        return $cache;   
    }
    
    /**
     * Вовзращает конфигурационый масив для frontendName
     * 
     * @param string $name frontendPage
     * @return array
     */
    protected function _getFrontendConfig($name)
    {
       $config = $this->_config->{$name}->toArray();
       if($config['logging'] === '1') {
           $config['logging'] = true;
           $config['logger'] = $this->_logger;
       }
       $debugHeader = Arm_Core::getEnvironment() === Arm_Core::ENVIRONMENT_STAGING ? false:true; 
       $config['debug_header'] = $debugHeader;
       $config['caching'] = $this->_cacheSystem;
       return $config;
    }
    
    
    /**
     * Помощник для установки frontendPage
     * @param array $array
     */
    protected function _helperPageConfig($array)
    {
        
        $result = array();
        foreach ($array as $k=>$v) {
            if(array_key_exists('reg', $v) === false or array_key_exists('cache', $v) === false) {
                throw new Arm_Cache_Exception(Arm_Translate::_('вы должны задать ключ reg и cache в конфиг файле 
                application/cache.ini секция frontendPage, правило "%s"', $k));
            }
            $reg = $v['reg'];
            unset($v['reg']);
            $result[$reg] = array();
            $v['cache'] = (bool) $v['cache'];
            $result[$reg] = $v;
        }
        return $result;
    }

    /**
     * Очистка всего кэша.
     * 
     * @return bool
     */
    public function cleanAll()
    {
       $this->getFrontendCore()->clean();
    }
    
    

}